<template>
  <Dialog :title="dialogTitle" v-model="dialogVisible">
    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      label-width="100px"
      v-loading="formLoading"
    >
      <el-form-item label="佐证" prop="evidenceUrl">
        <el-upload
          :headers="HEADERS"
          :file-list="formData.evidenceUrl"
          class="evidence-upload"
          :action="actionUrl"
          multiple
          list-type="text"
          :on-preview="handlePreview"
          :on-remove="handleRemove"
          :before-remove="beforeRemove"
          :on-success="handleUploadSuccess"
          :on-progress="handleUploadProgress"
          :before-upload="handleBeforeUpload"
          @update:file-list="(files) => formData.evidenceUrl = files"
        >
          <template #trigger>
            <el-button type="primary">文件上传</el-button>
          </template>
          <template #tip>
            <div class="el-upload__tip text-gray-500">
              文件大小不能超过20MB（VPN模式下尽量低于5MB）
            </div>
          </template>
        </el-upload>
        <!-- ai识别 -->
        <el-upload
          :show-file-list="false"
          :before-upload="beforeAIUpload"
          :http-request="handleAIUpload"
          accept="image/*,.pdf,.doc,.docx"
          style="display:inline-block;margin-left:12px;vertical-align:top;"
        >
          <el-button type="success" plain :loading="aiLoading">AI识别填表</el-button>
        </el-upload>
      </el-form-item>
      <el-form-item label="竞赛名称" prop="name">
        <el-input v-model="formData.name" placeholder="请输入竞赛名称" />
      </el-form-item>
      <el-form-item label="作品名称" prop="reserved1">
        <el-input v-model="formData.reserved1" placeholder="请输入作品名称" />
      </el-form-item>
      <el-form-item label="参赛学生" prop="reserved2">
        <el-input v-model="formData.reserved2" placeholder="请输入参赛学生" />
      </el-form-item>
      <el-form-item label="比赛级别" prop="type">
        <el-select v-model="formData.type" placeholder="请选择比赛级别" class="!w-240px">
          <el-option
            v-for="dict in getIntDictOptions(DICT_TYPE.COMPETITION_TYPE)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="主办方" prop="organizer">
        <el-select
          v-model="formData.organizer"
          placeholder="请选择主办方"
          clearable
          class="!w-240px"
        >
          <el-option
            v-for="dict in getIntDictOptions(DICT_TYPE.COMPETITION_ORGANIZER)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="其他主办方" prop="organizerOther">
        <el-input v-model="formData.organizerOther" placeholder="请输入其他主办方" />
      </el-form-item>
      <el-form-item label="获奖级别" prop="level">
        <el-select v-model="formData.level" placeholder="请选择获奖级别" clearable>
          <el-option
            v-for="dict in getIntDictOptions(DICT_TYPE.COMPETITION_LEVEL)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>

      <el-form-item label="奖项" prop="rank">
        <el-select v-model="formData.rank" placeholder="请选择奖项" clearable>
          <el-option
            v-for="dict in getIntDictOptions(DICT_TYPE.COMPETITION_RANK)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>

      </el-form-item>

      <el-form-item label="指导老师" prop="author">
        <el-select
          v-model="formData.author"
          filterable
          remote
          reserve-keyword
          placeholder="请输入名字搜索"
          :remote-method="remoteSearch"
          :loading="userLoading"
          class="!w-240px"
          @change="handleAuthorChange"
        >
          <el-option
            v-for="item in userOptions"
            :key="item.id"
            :label="getUserDisplayName(item.id)"
            :value="item.id"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="成员" prop="memberList">
        <div v-for="(member, index) in formData.memberList" :key="index" class="mb-4">
          <div class="flex items-center gap-4">
            <el-select
              v-model="member.userId"
              filterable
              remote
              reserve-keyword
              placeholder="请输入名字搜索"
              :remote-method="remoteSearch"
              :loading="userLoading"
              class="!w-240px"
              @change="() => handleMemberChange(index)"
            >
              <el-option
                v-for="item in userOptions"
                :key="item.id"
                :label="getUserDisplayName(item.id)"
                :value="item.id"
              />
            </el-select>
            <el-input-number
              v-model="member.rate"
              :min="1"
              :max="100"
              :precision="0"
              style="width: 150px;"
              placeholder="贡献率%"
            />
            <el-button
            type="danger"
            link
            :icon="Delete"
            @click="removeMember(index)"
            v-if="index !== 0"
          />
          </div>
        </div>
        <el-button type="primary" link @click="addMember">
          <Icon icon="ep:plus" class="mr-5px" />添加成员
        </el-button>
      </el-form-item>
      <el-form-item label="获奖时间" prop="competitionTime">
        <el-date-picker
          v-model="formData.competitionTime"
          type="date"
          value-format="x"
          placeholder="选择获奖时间"
        />
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
      <el-button @click="dialogVisible = false">取 消</el-button>
    </template>
  </Dialog>
</template>

<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CompetitionApi } from '@/api/digital/competition'
import * as UserApi from '@/api/system/user'
import { getAccessToken } from '@/utils/auth'
import { ElMessageBox, ElMessage } from 'element-plus'
import { Delete, Plus } from '@element-plus/icons-vue'
import axios from 'axios'

defineOptions({ name: 'CompetitionForm' })

const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中：1）打开表单时的数据加载；2）提交表单时的数据提交
const formType = ref('') // 表单的类型：create - 新增；update - 修改
const actionUrl = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/infra/file/upload'
const HEADERS = { Authorization: 'Bearer ' + getAccessToken() }

// 表单数据
const formData = ref({
  id: undefined,
  name: '',
  type: undefined,
  organizer: undefined,
  organizerOther: '',
  level: undefined,
  rank: undefined,
  author: undefined,
  competitionTime: undefined,
  evidenceUrl: [], // 确保初始值是空数组
  memberList: [{ userId: undefined, rate: 100 }], // 初始化一个成员，贡献率为100
  remark: undefined,
  reserved1: undefined,
  reserved2: undefined
})

// 表单校验规则
const formRules = ref({
  name: [{ required: true, message: '竞赛名称不能为空', trigger: 'change' }],
  type: [{ required: true, message: '比赛级别不能为空', trigger: 'change' }],
  level: [{ required: true, message: '获奖级别不能为空', trigger: 'change' }],
  rank: [{ required: true, message: '奖项不能为空', trigger: 'change' }],
  author: [{ required: true, message: '指导老师不能为空', trigger: 'change' }],
  competitionTime: [
    { required: true, message: '获奖时间不能为空', trigger: 'change' },
    {
      validator: (rule, value, callback) => {
        if (value) {
          // value是时间戳（毫秒），需要转换为日期进行比较
          const competitionDate = new Date(Number(value))
          const today = new Date()
          today.setHours(23, 59, 59, 999) // 设置为今天的最后一刻
          
          if (competitionDate > today) {
            callback(new Error('获奖时间不能晚于今天'))
          } else {
            callback()
          }
        } else {
          callback()
        }
      },
      trigger: 'change'
    }
  ],
  evidenceUrl: [{ required: true, message: '佐证不能为空', trigger: 'change' }],
  memberList: [
    {
      type: 'array',
      required: true,
      validator: (rule, value, callback) => {
        if (!value || value.length === 0) {
          callback(new Error('成员不能为空'))
          return
        }

        // 检查是否所有必填字段都已填写
        const hasEmptyFields = value.some(
          (item) => item.userId === undefined || item.rate === undefined || item.rate === null
        )
        if (hasEmptyFields) {
          callback(new Error('请填写完整的成员信息和贡献率'))
          return
        }

        // 检查贡献率是否在有效范围内
        const hasInvalidRate = value.some(
          (item) => item.rate < 1 || item.rate > 100
        )
        if (hasInvalidRate) {
          callback(new Error('贡献率必须在1%到100%之间'))
          return
        }

        // 检查是否有重复成员
        const userIds = value.map(item => item.userId).filter(id => id !== undefined)
        const uniqueUserIds = new Set(userIds)
        if (userIds.length !== uniqueUserIds.size) {
          callback(new Error('成员不能重复'))
          return
        }

        // 检查贡献率总和是否为100
        const totalRate = value.reduce((sum, item) => sum + (item.rate || 0), 0)
        if (totalRate !== 100) {
          callback(new Error('贡献率总和必须等于100%'))
          return
        }
        callback()
      },
      trigger: 'change'
    }
  ]
})

// 表单操作
const formRef = ref() // 表单 Ref
const emit = defineEmits(['success']) // 定义 success 事件，用于操作成功后的回调

// 处理作者变化
const handleAuthorChange = async (value) => {
  if (value) {
    // 确保用户数据已加载
    await initUserOptions()
    formData.value.memberList[0].userId = value
    formData.value.memberList[0].rate = 100 // 默认设置第一作者贡献率为100
    // 更新用户映射
    const user = userOptions.value.find(item => item.id === value)
    if (user && !userMap.value.has(user.id)) {
      userMap.value.set(user.id, user)
    }
  }
}

// 处理成员变化
const handleMemberChange = async (index) => {
  // 确保用户数据已加载
  await initUserOptions()
  
  // 如果是第一个成员（第一作者），同步更新author
  if (index === 0) {
    formData.value.author = formData.value.memberList[0].userId
  }
  // 更新用户映射
  const userId = formData.value.memberList[index].userId
  const user = userOptions.value.find(item => item.id === userId)
  if (user && !userMap.value.has(user.id)) {
    userMap.value.set(user.id, user)
  }
}

// 用户选择相关
const userLoading = ref(false)
const userOptions = ref([])
const userMap = ref(new Map())

// 远程搜索用户
const remoteSearch = async (query: string) => {
  if (query !== '') {
    userLoading.value = true
    try {
      // 确保基础用户数据已加载
      await initUserOptions()
      
      const data = await UserApi.searchUser(query)
      data.forEach(user => {
        if (!userMap.value.has(user.id)) {
          userMap.value.set(user.id, user)
        }
      })
      userOptions.value = data
    } finally {
      userLoading.value = false
    }
  } else {
    userOptions.value = Array.from(userMap.value.values())
  }
}

// 初始化用户列表
const initUserOptions = async () => {
  try {
    const data = await UserApi.getAllUser()
    data.forEach(user => {
      userMap.value.set(user.id, user)
    })
    userOptions.value = data
    return data  // 返回数据以便确认加载完成
  } catch (error) {
    console.error('获取用户列表失败:', error)
    return []
  }
}

// 获取用户显示名称
const getUserDisplayName = (userId: number) => {
  const user = userMap.value.get(userId)
  if (user) {
    return `${user.username}${user.nickname ? ` (${user.nickname})` : ''}`
  }
  return ''  // 当找不到用户时返回空字符串
}

// 文件上传相关
const handleUploadProgress = (event: any, uploadFile: any) => {
  uploadFile.percentage = Math.round(event.loaded * 100 / event.total)
}

const handleBeforeUpload = (file: File) => {
  const maxSize = 20 * 1024 * 1024
  if (file.size > maxSize) {
    ElMessage.error('文件大小不能超过20MB')
    return false
  }
  return true
}

const handleUploadSuccess = (response: any, uploadFile: any) => {
  if (response.code === 0) {
    const url = response.data
    uploadFile.url = url
    uploadFile.status = 'success'
    // 清除表单验证错误
    formRef.value?.clearValidate(['evidenceUrl'])
  } else {
    ElMessage.error('上传失败：' + response.msg)
    uploadFile.status = 'error'
  }
}

const handleRemove = (file: any, uploadFiles: any[]) => {
  // 如果没有文件了，重新触发验证
  if (uploadFiles.length === 0) {
    formRef.value?.validateField('evidenceUrl')
  }
}

const handlePreview = (uploadFile: any) => {
  window.open(uploadFile.url)
}

const beforeRemove = async (uploadFile: any, uploadFiles: any[]) => {
  // 如果是因为文件大小超限而被拒绝的文件，直接删除不提示
  if (!uploadFile.url && uploadFile.status === 'ready') {
    return true
  }
  // 正常删除时显示确认提示
  return await ElMessageBox.confirm(`确认删除 ${uploadFile.name} 吗?`)
}

// 重置表单
const resetForm = () => {
  formData.value = {
    id: undefined,
    name: '',
    type: undefined,
    organizer: undefined,
    organizerOther: '',
    level: undefined,
    rank: undefined,
    author: undefined,
    competitionTime: undefined,
    evidenceUrl: [],
    memberList: [{ userId: undefined, rate: 100 }], // 初始化一个成员，贡献率为100
    remark: undefined,
    reserved1: undefined,
    reserved2: undefined
  }
  if (formRef.value) {
    formRef.value.resetFields()
  }
}

// 提交表单
const submitForm = () => {
  formRef.value?.validate(async (valid: boolean) => {
    if (!valid) return
    
    formLoading.value = true
    try {
      // 处理成员和贡献率数据
      const memberIds = formData.value.memberList
        .filter(member => member.userId)
        .map(member => member.userId)
      const rates = formData.value.memberList
        .filter(member => member.userId)
        .map(member => member.rate)

      const data = {
        ...formData.value,
        evidenceUrl: formData.value.evidenceUrl
          .filter(file => file.response || file.url)
          .map(file => file.response?.data || file.url),
        member: memberIds.join(','),
        rate: rates.join(','),
        organizer: formData.value.organizer === undefined ? null : formData.value.organizer // 确保空值也传出去
      }
      
      if (formType.value === 'create') {
        await CompetitionApi.createCompetition(data)
        ElMessage.success('创建成功')
      } else {
        await CompetitionApi.updateCompetition(data)
        ElMessage.success('更新成功')
      }
      dialogVisible.value = false
      emit('success')
    } catch (error) {
      ElMessage.error('操作失败：' + error.message)
    } finally {
      formLoading.value = false
    }
  })
}

const addMember = () => {
  formData.value.memberList.push({ userId: undefined, rate: 0 })
  // 如果只有一个成员，设置其贡献率为100
  if (formData.value.memberList.length === 1) {
    formData.value.memberList[0].rate = 100
  }
}

const removeMember = (index: number) => {
  formData.value.memberList.splice(index, 1)
  // 如果只剩一个成员，设置其贡献率为100
  if (formData.value.memberList.length === 1) {
    formData.value.memberList[0].rate = 100
  }
}

// 打开弹窗
const open = async (type: string, id?: number) => {
  dialogVisible.value = true
  dialogTitle.value = type === 'create' ? '新增竞赛' : '编辑竞赛'
  formType.value = type
  resetForm()
  formLoading.value = true
  
  try {
    // 确保用户数据已加载完成
    await initUserOptions()
    
    // 修改时，设置数据
    if (id) {
      const data = await CompetitionApi.getCompetition(id)
      
      // 转换文件URL为文件对象
      if (data.evidenceUrl) {
        if (typeof data.evidenceUrl === 'string') {
          data.evidenceUrl = [convertUrlToFileObject(data.evidenceUrl)]
        } else if (Array.isArray(data.evidenceUrl)) {
          data.evidenceUrl = data.evidenceUrl.map(url => convertUrlToFileObject(url))
        }
      } else {
        data.evidenceUrl = []
      }

      // 确保memberList存在且格式正确
      if (!data.memberList || !Array.isArray(data.memberList)) {
        data.memberList = [{ userId: data.author, rate: 100 }]
      }

      // 更新表单数据
      formData.value = data
      // 确保作者ID是数字类型
      if (formData.value.author) {
        formData.value.author = Number(formData.value.author)
      }
      
      // 如果有成员数据，转换为memberList格式
      if (formData.value.member && formData.value.rate) {
        const memberIds = formData.value.member.split(',')
        const rates = formData.value.rate.split(',')
        formData.value.memberList = memberIds.map((id, index) => ({
          userId: Number(id),
          rate: Number(rates[index])
        }))
      } else {
        formData.value.memberList = [{ userId: undefined, rate: 0 }]
      }
    }
  } finally {
    formLoading.value = false
  }
}

// 将URL转换为文件对象
const convertUrlToFileObject = (url: string) => {
  return {
    name: url.split('/').pop() || 'file',
    url: url,
    status: 'success'
  }
}

defineExpose({ open })

// 组件挂载时初始化用户列表
onMounted(async () => {
  await initUserOptions()
})

const aiLoading = ref(false)

// AI识别上传前校验
const beforeAIUpload = (file: File) => {
  const maxSize = 20 * 1024 * 1024
  if (file.size > maxSize) {
    ElMessage.error('文件大小不能超过20MB')
    return false
  }
  return true
}

// AI识别自定义上传
const handleAIUpload = async ({ file }) => {
  aiLoading.value = true
  try {
    const formDataUpload = new FormData()
    formDataUpload.append('file', file)
    const res = await axios.post('/ai/competition', formDataUpload, {
      headers: { 'Content-Type': 'multipart/form-data', ...HEADERS, 'tenant-id': '1' }
    })
    console.log('AI识别返回：', res.data) // 调试用
    if (res.data && res.data.code === 0 && res.data.msg) {
      fillFormByAIResult(res.data.msg)
      ElMessage.success('识别成功，表单已自动填充')
    } else {
      ElMessage.error('识别失败：' + (res.data?.msg || '未知错误'))
    }
  } catch (e) {
    ElMessage.error('识别失败')
  } finally {
    aiLoading.value = false
    return false
  }
}

// 解析AI识别结果并填充表单
function fillFormByAIResult(result) {
  let dataObj
  try {
    dataObj = typeof result === 'string' ? JSON.parse(result) : result
  } catch {
    ElMessage.error('识别内容解析失败')
    return
  }

  // 处理 member 字段
  let memberArr = []
  try {
    memberArr = JSON.parse(dataObj.member)
    memberArr = memberArr.map(id => Number(id))
  } catch {
    memberArr = String(dataObj.member).replace(/[\[\]\"]/g, '').split(',').map(id => Number(id.trim()))
  }

  // 指导老师
  if (memberArr.length > 0 && userOptions.value.some(user => user.id === memberArr[0])) {
    formData.value.author = memberArr[0]
  }

  // 贡献率
  let rateArr = []
  if (dataObj.rate) {
    rateArr = String(dataObj.rate).split(',').map(r => Number(r.trim()))
  }

  // 成员
  const validMembers = memberArr.filter(id => userOptions.value.some(user => user.id === id));
  const avgRate = validMembers.length > 0 ? Math.floor(100 / validMembers.length) : 0;
  let remain = 100 - avgRate * validMembers.length; // 处理整除后余数
  
  formData.value.memberList = validMembers.map((id, idx) => ({
    userId: id,
    rate: idx === 0 ? avgRate + remain : avgRate // 把余数加到第一个人身上，保证总和为100
  }));

  // 其他字段自动赋值
  Object.keys(dataObj).forEach(key => {
  if (['member', 'rate','author'].includes(key)) return
  if (key === 'evidenceUrl' && Array.isArray(dataObj[key])) {
    formData.value.evidenceUrl = dataObj[key].map((url, idx) => ({
      name: typeof url === 'string' ? url.split('/').pop() : `file${idx}`,
      url: url,
      status: 'success',
      uid: Date.now() + idx
    }))
  } else if (key === 'competitionTime') {
    // 处理AI返回的日期格式，转为时间戳
    let val = dataObj[key]
    if (typeof val === 'string' && val) {
      // 支持"2024-05-01"或"2024/05/01"等格式
      const date = new Date(val.replace(/-/g, '/'))
      if (!isNaN(date.getTime())) {
        formData.value.competitionTime = date.getTime()
      } else {
        formData.value.competitionTime = undefined
      }
    } else if (typeof val === 'number') {
      formData.value.competitionTime = val
    } else {
      formData.value.competitionTime = undefined
    }
  } else if (formData.value.hasOwnProperty(key)) {
    formData.value[key] = dataObj[key]
  } 
})
}
</script>

<style scoped>
.evidence-upload {
  width: 360px;
}
</style>
